using System;
using System.Collections.Generic;

namespace Leet
{
    class Profiler
    {
        public static Dictionary<string, DateTime> m_dic = new Dictionary<string, DateTime>();
        public static void Start()
        {
            string tag = "";
            m_dic[tag] = DateTime.UtcNow;
        }

        public static TimeSpan End()
        {
            string tag = "";
            if (!m_dic.ContainsKey(tag))
            {
                throw new Exception("No start time of: " + tag);
            }
            var start = m_dic[tag];
            var end = DateTime.UtcNow;

            return end - start;
        }

        public static void Start(string tag)
        {
            m_dic[tag] = DateTime.UtcNow;
        }

        public static TimeSpan End(string tag)
        {
            if (!m_dic.ContainsKey(tag))
            {
                throw new Exception("No start time of: " + tag);
            }
            var start = m_dic[tag];
            var end = DateTime.UtcNow;

            var span = end - start;
            Console.WriteLine(tag + ": time used:" + span.TotalMilliseconds + "ms");

            return span;
        }

        public static R Run<T, R>(Func<T, R> func, T param0)
        {
            Profiler.Start();
            R r = func(param0);
            var span = Profiler.End();
            Console.WriteLine("time used:" + span.TotalMilliseconds + "ms");
            return r;
        }

        public static R Run<T1, T2, R>(Func<T1, T2, R> func, T1 param0, T2 param1)
        {
            Profiler.Start();
            R r = func(param0, param1);
            var span = Profiler.End();
            Console.WriteLine("time used:" + span.TotalMilliseconds + "ms");
            return r;
        }

        public static R Run<T, R>(Func<T, R> func, T param0, Action<R> postFunc)
        {
            Profiler.Start();
            R r = func(param0);
            var span = Profiler.End();
            postFunc(r);
            Console.WriteLine("time used:" + span.TotalMilliseconds + "ms");
            return r;
        }

        public static R Run<T1, T2, R>(Func<T1, T2, R> func, T1 param0, T2 param1, Action<R> postFunc)
        {
            Profiler.Start();
            R r = func(param0, param1);
            var span = Profiler.End();
            postFunc(r);
            Console.WriteLine("time used:" + span.TotalMilliseconds + "ms");
            return r;
        }
    }
}